/*
 **	Skeleton.h

 Program: glutMOCAPviewer  
 Language: C++
 Date:  Dec 10 2007      
 Version: 0.1   

 **      Created: Nov 23 2007.
 **	
 **	purpose: Read a skeleton file from various formats
 */

#ifndef __SKELETON_H__
#define __SKELETON_H__

#include <string>
#include <vector>
#include <map>
#include <list>
#include <sstream>
#include <fstream>
#include <iostream>

#include "Vector.h"
#include "Bone.h"

using namespace std;

/**
 * This class implements a skeleton for store data readed 
 * from a skeleton file in various formats.
 */
class Skeleton {
public:

    /**
     * Edge type.
     */
    typedef pair<Vector3d, Vector3d>        Edge;

    /** 
     * Pose type - configuration of arbitrary skeleton.
     */ 
    typedef map<string, Edge>               Pose;
    
    /**
     * Joints type
     */
    typedef map<string, Vector3d>           Joints;

    /**
     * An enum specifying types of commands.
     */
    enum CmdValues {
        cmdVersion, /**< enum value cmdVersion. */
        cmdName, /**< enum value cmdName. */
        cmdUnits, /**< enum value cmdUnits. */
        cmdDoc, /**< enum value cmdDoc. */
        cmdRoot, /**< enum value cmdRoot. */
        cmdBoneData, /**< enum value cmdBoneData. */
        cmdHierarchy /**< enum value cmdHierarchy. */
    };

    /**
     * A constructor. Default constructor.
     */
    Skeleton() {
    }

    /**
     * A constructor.
     * Constructor parsing skeleton and motion files (ASF/AMC).
     * @param skeletonFile name of skeleton file (ASF)
     * @param motionFile name of motion file (AMC)
     */
    Skeleton(string skeletonFile, string motionFile);
    
    /**
	 * A constructor.
	 * Constructor parsing bvh file
	 * @param bvhFile name of file (BVH)
	 */
	Skeleton(string bvhFile);

    /**
     * Build a pose corresponding to current skeleton.
     * @param root_position actual position of root
     * @param current_skeleton given skeleton
     * @return The pose constructed
     */
    Pose buildPose(Vector3d root_position, map<string, Bone> current_skeleton);

    /**
     * Create an default joints map.
     * @return joints structure
     */
    map<string, Vector3d> createJoints();

    /**
     * Rotate around generic axis.
     * @param angle given rotation angle
     * @param vec given vector for rotation
     * @param axis given rotation axis
     * @return rotated vector 
     */
    Vector3d rotate(double angle, Vector3d vec, Vector3d axis);
    
    /** 
     * Get a color of bone.
     * @param bone given bone
     * @return color of bone
     */
    inline Vector3d getBoneColor(string bone) {
        return bones[bone].getColor();
    }

    /**
     * Get a pose from animation.
     * @param i given position
     * @return ith pose of animation
     */
    inline Pose getPose(int i) {
        return motion[i];
    }

    /**
     * Get the number of frames of the animation.
     * @return motion size
     */
    inline int getMotionSize() {
        return motion.size();
    }

    /**
     * Get a skeleton of arbitrary frame of animation.
     * @param i given frame
     * @return skeleton correspondent
     * */
    inline map<string, Bone> getSkeleton(int i) {
        return skeletons[i];
    }

    /**
     * Parse command string to enum value.
     * @param command to parse
     * @return CmdValue correspondent
     */
    CmdValues cmdToEnum(string command);

    /**
     * Read words in a line.
     * @param line a line for break in words
     * @return vctor of words in line
     */
    vector<string> readWords(string line);

    /**
     * Read an ASF skeleton file.
     * @param asfFile name of file
     * @return read sucefully or not
     */
    bool loadASF(string asfFile);

    /**
     * Read an AMC motion data file.
     * @param amcFile name of file
     * @return read sucefully or not
     */
    bool loadAMC(string amcFile);
    
    /**
     * Read a BVH file
     * @param bvhFile name of file
     * @return read sucefully or not
     */
    bool loadBVH(string bvhFile);
    
    /**
     * Export animation on pss format.
     * @param skelInFile given skel input file
     * @param pssFile name of file
     * @return export sucefully or not
     */
    bool exportPSS(string skelInFile, string pssFile);
    
private:
    string                          version; /**< Version of file format. */
    string                          name; /**< Name of skeleton. */
    string                          doc; /**< Documentation follows. */
    double                          mass; /**< Mass unit definition: multipliers for different unit systems. */
    double                          length; /**< Length unit definition: local units in inches. */
    bool                            is_degree; /**< Angle unit definition: rad or deg - degrees are default */
    
    // root atributes
    string                          axis; /**< Rotation order for orientation offset. */
    string                          order; /**< Order of transformations for root. */
    Vector3d                        position; /**< Translation data for root node. To position the skeleton. */
    Vector3d                        orientation; /**< Rotation data. To orient the skeleton */
    
    // skeleton bones
    map<string, Bone>               bones; /**< The bones of default skeleton (Readed of file). */
    vector< map<string, Bone> >     skeletons; /**< Skeletons of each frame in animation */
    
    // bones hierarchy
    map<string, vector<string> >    hierarchy; /**< Hierarchy of bones. */    
    
    // poses
    Pose                            initial_pose; /**< Initial position of joints. Readed of skeleton file. */
    vector<Pose>                    motion; /**< Vector of skeleton poses. The animation. */

public:
    vector<Joints>                  joints; /**< Vector of joint positions during animation. */
    Vector3d                        minPoint,
                                    maxPoint;
};

#endif
